#include "ProductionBasic.h"
#include "ProductionParser.h"
#include "ProductionIMPL.h"
#include <string>

using namespace std;


CProduction::CProduction( std::string str ,boost::shared_ptr<IMPL> pIMPL):
m_String(str),
m_pImplement(pIMPL),
m_argLength(0)
{
    
    if (!m_pImplement)
    {
        m_pImplement = CProductionIMPLPtr(new CProductionIMPL_trivial());
    }

    try
    {
        CProductionParser p;
        vector<Token_Type> vec = p.Parse(str);

        if (!vec.empty())
        {
            m_Left = vec[0];

            for (int i = 1; i != vec.size(); ++i)
            {
                if (vec[i] != TOKEN_EMPTY)
                {
                    ++m_argLength;
                }
                m_Right.push_back(vec[i]);
            }

        }
    }
    catch (production_exception& e)
    {
        m_Left = TOKEN_ERROR;
        m_Right.clear();
        e << current_production(str);
        LOG("production_exception : %s",diagnostic_information(e));
    }

}



CProduction::~CProduction()
{

}




const std::vector<Token_Type>& CProduction::Right()
{
    return m_Right;
}

const Token_Type CProduction::Left()
{
    return m_Left;
}


int CProduction::Length()
{
    return m_Right.size();
}


const char* CProduction::toString()
{
    return m_String.c_str();
}

CTokenPtr CProduction::Reduce( CProductionArgPtr pArgs )
{
	LOG("CProduction::Reduce %s",toString());

    CTokenPtr pToken = m_pImplement->Reduce(pArgs);

	pToken->SetType(Left());

	return pToken;
}

int CProduction::ArgLength()
{
    return m_argLength;
}



